using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
using System.IO;

namespace mapeditor
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        const int nbre_max = 150;
        const int cote_caisse = 34;
        
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;

        SpriteList ecran;
        table2d caisseList;
        Sprite plateforme, caisse, platg, platd, sentinelle, helico, soldat;
        MouseState souris;
        KeyboardState clavier;
        int k, ligne, colonne, taille_ecran;
        bool positionEmpty;
        TimeSpan timer;
        int coefx, coefy;
        SpriteFont texte;
        bool save, load;
        string[,] caisseList2;
        string typeObj;

        int longueur_map;
        int hauteur_map;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";

            graphics.PreferredBackBufferWidth = 800;
            graphics.PreferredBackBufferHeight = 600;
            graphics.ApplyChanges();

            IsMouseVisible = true;
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            // TODO: Add your initialization logic here
            taille_ecran = (graphics.PreferredBackBufferWidth / cote_caisse) * (graphics.PreferredBackBufferHeight / cote_caisse) + 150;
            ligne = 0;
            colonne = 0;
            k = 0;
            typeObj = "C";
            positionEmpty = true;
            longueur_map = (graphics.PreferredBackBufferWidth / cote_caisse) * 10;
            hauteur_map = (graphics.PreferredBackBufferHeight / cote_caisse) + 1;
            caisseList = new table2d(taille_ecran * 10);
            caisseList2 = new string[hauteur_map, longueur_map];
            ecran = new SpriteList(taille_ecran);
            ecran.Init();
            caisseList.Init();
            plateforme = new Sprite();
            caisse = new Sprite();
            platg = new Sprite();
            platd = new Sprite();
            sentinelle = new Sprite();
            helico = new Sprite();
            soldat = new Sprite();
            coefx = 0;
            coefy = 0;
            save = false;
            load = false;

            for (int i = 0; i < taille_ecran && (ligne * cote_caisse) <= graphics.PreferredBackBufferHeight; i++)
            {
                if (colonne >= graphics.PreferredBackBufferWidth)
                {
                    ligne++;
                    colonne = 0;
                }
                else
                {
                    ecran.tableau[i, 0] = colonne;
                    ecran.tableau[i, 1] = ligne * cote_caisse;
                    colonne += cote_caisse;
                }
            }

            for (int x = 0; x < caisseList2.GetLength(0); x++)
            {
                for (int y = 0; y < caisseList2.GetLength(1); y++)
                {
                    caisseList2[x, y] = ".";
                }
            }

            Menu.Initialize();

            base.Initialize();
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);

            // TODO: use this.Content to load your game content here
            plateforme.Load(Content, "plateforme");
            caisse.Load(Content, "caisse");
            platg.Load(Content, "platg");
            platd.Load(Content, "platd");
            sentinelle.Load(Content, "senti");
            soldat.Load(Content, "soldat");
            helico.Load(Content, "heli");
            texte = Content.Load<SpriteFont>("points");

            Menu.LoadContent(Content);
        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        protected override void Update(GameTime gameTime)
        {
            // Allows the game to exit
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                this.Exit();

            // TODO: Add your update logic here
            souris = Mouse.GetState();
            clavier = Keyboard.GetState();

            if (souris.X >= 700)
            {
                Menu.Update(ref typeObj, ref save, ref load);
            }
            else
            {
                if (souris.LeftButton == ButtonState.Pressed && timer.Milliseconds >= 60)
                {
                    timer = TimeSpan.Zero;

                    for (int i = 0; i < taille_ecran; i++)
                    {
                        if (souris.X >= ecran.tableau[i, 0] && souris.X <= (ecran.tableau[i, 0] + cote_caisse) && souris.Y >= ecran.tableau[i, 1] && souris.Y <= (ecran.tableau[i, 1] + cote_caisse))
                        {
                            /*
                            for (int j = 0; j < taille_ecran && positionEmpty; j++)
                            {
                                if (caisseList.tableau[j, 1] - coefx == ecran.tableau[i, 0] && caisseList.tableau[j, 2] - coefy == ecran.tableau[i, 1])
                                {
                                    positionEmpty = false;
                                }
                            }

                            if (positionEmpty)
                            {
                                caisseList.tableau[k, 0] = typeObj;
                                caisseList.tableau[k, 1] = ecran.tableau[i, 0] + coefx;
                                caisseList.tableau[k, 2] = ecran.tableau[i, 1] + coefy;
                                k++;
                                k = k % (taille_ecran * 10);
                                return;
                            }

                            positionEmpty = true;
                            */

                            if (caisseList2[(ecran.tableau[i, 1] + coefy) / cote_caisse, (ecran.tableau[i, 0] + coefx) / cote_caisse] == ".")
                            {
                                caisseList2[(ecran.tableau[i, 1] + coefy) / cote_caisse, (ecran.tableau[i, 0] + coefx) / cote_caisse] = typeObj;
                                break;
                            }
                        }
                    }
                }
                else if (souris.RightButton == ButtonState.Pressed)
                {
                    /*
                    for (int i = 0; i <= k; i++)
                    {
                        if (souris.X >= caisseList.tableau[i, 1] - coefx && souris.X <= (caisseList.tableau[i, 1] + cote_caisse - coefx) && souris.Y >= caisseList.tableau[i, 2] - coefy && souris.Y <= (caisseList.tableau[i, 2] + cote_caisse - coefy))
                        {
                            caisseList.tableau[i, 1] = -1;
                            caisseList.tableau[i, 2] = -1;
                            break;
                        }
                    }
                    */

                    for (int i = 0; i < taille_ecran; i++)
                    {
                        if (souris.X >= ecran.tableau[i, 0] && souris.X <= (ecran.tableau[i, 0] + cote_caisse) && souris.Y >= ecran.tableau[i, 1] && souris.Y <= (ecran.tableau[i, 1] + cote_caisse))
                        {
                            caisseList2[(ecran.tableau[i, 1] + coefy) / cote_caisse, (ecran.tableau[i, 0] + coefx) / cote_caisse] = ".";
                            break;
                        }
                    }
                }
            }
            if ((clavier.IsKeyDown(Keys.S) && timer.Milliseconds >= 60) || save)
            {
                if (File.Exists(@"map.txt"))
                {
                    File.Delete(@"map.txt");
                }

                using (StreamWriter sw = File.CreateText("map.txt"))
                {
                    /*
                    for (int i = 0; i < taille_ecran * 10; i++)
                    {
                        if (caisseList.tableau[i, 1] != -1 && caisseList.tableau[i, 2] != -1)
                        {
                            sw.WriteLine(caisseList.tableau[i, 0] + " " + caisseList.tableau[i, 1] + " " + caisseList.tableau[i, 2]);
                        }
                    }
                    */

                    for (int x = 0; x < caisseList2.GetLength(0); x++)
                    {
                        for (int y = 0; y < caisseList2.GetLength(1); y++)
                        {
                            sw.Write(caisseList2[x, y]);
                        }

                        sw.WriteLine();
                    }

                    sw.Close();
                }

                save = false;
                timer = TimeSpan.Zero;
            }
            else if ((clavier.IsKeyDown(Keys.C) && timer.Milliseconds >= 60) || load)
            {
                caisseList.Init();

                using (StreamReader sr = File.OpenText("map.txt"))
                {
                    /*
                    string line;
                    int start, end, type, x, y;

                    for (int i = 0; (line = sr.ReadLine()) != null; i++)
                    {
                        start = 0;
                        for (end = start; line[end] != ' '; end++) ;
                        type = int.Parse(line.Substring(start, (end - start)));

                        start = end + 1;
                        for (end = start; line[end] != ' '; end++) ;
                        x = int.Parse(line.Substring(start, (end - start)));

                        start = end + 1;
                        for (end = start; line[end] != ' ' && end < line.Length - 1; end++) ;
                        y = int.Parse(line.Substring(start, (end - start + 1)));

                        caisseList.tableau[i, 0] = type;
                        caisseList.tableau[i, 1] = x;
                        caisseList.tableau[i, 2] = y;
                        k = i;
                    }
                    k++;
                    */

                    string line;

                    for (int x = 0; x < caisseList2.GetLength(0) && (line = sr.ReadLine()) != null; x++)
                    {
                        for (int y = 0; y < caisseList2.GetLength(1) && y < line.Length; y++)
                        {
                            caisseList2[x, y] = line[y].ToString();
                        }
                    }

                    sr.Close();
                }

                load = false;
                timer = TimeSpan.Zero;
            }

            if (clavier.IsKeyDown(Keys.Right) && coefx <= (longueur_map * cote_caisse - 2 * graphics.PreferredBackBufferWidth))
            {
                coefx += cote_caisse;
            }

            if (clavier.IsKeyDown(Keys.Left) && coefx > 0)
            {
                coefx -= cote_caisse;
            }

            if (clavier.IsKeyDown(Keys.Up) && coefy >= graphics.PreferredBackBufferHeight - hauteur_map * cote_caisse)
            {
                coefy -= cote_caisse;
            }

            if (clavier.IsKeyDown(Keys.Down) && coefy <= hauteur_map - graphics.PreferredBackBufferHeight)
            {
                coefy += cote_caisse;
            }

            if (clavier.IsKeyDown(Keys.NumPad1))
            {
                typeObj = "C";
            }
            else if (clavier.IsKeyDown(Keys.NumPad2))
            {
                typeObj = "o";
            }
            else if (clavier.IsKeyDown(Keys.NumPad3))
            {
                typeObj = "<";
            }
            else if (clavier.IsKeyDown(Keys.NumPad4))
            {
                typeObj = ">";
            }

            if (typeObj == "C")
            {
                caisse.Position.X = souris.X - (caisse.Size.Width / 2);
                caisse.Position.Y = souris.Y - (caisse.Size.Height / 2);
            }
            else if (typeObj == "o")
            {
                plateforme.Position.X = souris.X - (plateforme.Size.Width / 2);
                plateforme.Position.Y = souris.Y - (plateforme.Size.Height / 2);
            }
            else if (typeObj == "<")
            {
                platg.Position.X = souris.X - (platg.Size.Width / 2);
                platg.Position.Y = souris.Y - (platg.Size.Height / 2);
            }
            else if (typeObj == ">")
            {
                platd.Position.X = souris.X - (platd.Size.Width / 2);
                platd.Position.Y = souris.Y - (platd.Size.Height / 2);
            }
            else if (typeObj == "s")
            {
                sentinelle.Position.X = souris.X - (sentinelle.Size.Width / 2);
                sentinelle.Position.Y = souris.Y - (sentinelle.Size.Height / 2);
            }
            else if (typeObj == "h")
            {
                helico.Position.X = souris.X - (helico.Size.Width / 2);
                helico.Position.Y = souris.Y - (helico.Size.Height / 2);
            }
            else if (typeObj == "e")
            {
                soldat.Position.X = souris.X - (soldat.Size.Width / 2);
                soldat.Position.Y = souris.Y - (soldat.Size.Height / 2);
            }

        timer += gameTime.ElapsedGameTime;

            base.Update(gameTime);
        }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.Black);

            // TODO: Add your drawing code here
            spriteBatch.Begin();
            /*
            for (int i = 0; i < caisseList.nbre_cases; i++)
            {
                if (caisseList.tableau[i, 1] - coefx >= 0 && caisseList.tableau[i, 1] - coefx <= graphics.PreferredBackBufferWidth && caisseList.tableau[i, 2] - coefy <= graphics.PreferredBackBufferHeight && caisseList.tableau[i, 2] - coefy >= 0 && (caisseList.tableau[i, 1] != -1 || caisseList.tableau[i, 2] != -1))
                {
                    if (caisseList.tableau[i, 0] == 1)
                    {
                        spriteBatch.Draw(caisse.Texture, new Vector2(caisseList.tableau[i, 1] - coefx, caisseList.tableau[i, 2] - coefy), Color.White);
                    }
                    else if (caisseList.tableau[i, 0] == 2)
                    {
                        spriteBatch.Draw(plateforme.Texture, new Vector2(caisseList.tableau[i, 1] - coefx, caisseList.tableau[i, 2] - coefy), Color.White);
                    }
                    else if (caisseList.tableau[i, 0] == 3)
                    {
                        spriteBatch.Draw(platg.Texture, new Vector2(caisseList.tableau[i, 1] - coefx, caisseList.tableau[i, 2] - coefy), Color.White);
                    }
                    else if (caisseList.tableau[i, 0] == 4)
                    {
                        spriteBatch.Draw(platd.Texture, new Vector2(caisseList.tableau[i, 1] - coefx, caisseList.tableau[i, 2] - coefy), Color.White);
                    }
                }
            }
            */

            for (int x = 0; x < caisseList2.GetLength(0); x++)
            {
                for (int y = 0; y < caisseList2.GetLength(1); y++)
                {
                    if (x * cote_caisse - coefy <= graphics.PreferredBackBufferHeight && y * cote_caisse - coefx <= graphics.PreferredBackBufferWidth && x * cote_caisse  - coefy>= 0 && y * cote_caisse - coefx >= 0)
                    {
                        if (caisseList2[x, y] == "C")
                        {
                            spriteBatch.Draw(caisse.Texture, new Vector2(y * cote_caisse - coefx, x * cote_caisse - coefy), Color.White);
                        }
                        else if (caisseList2[x, y] == "o")
                        {
                            spriteBatch.Draw(plateforme.Texture, new Vector2(y * cote_caisse - coefx, x * cote_caisse - coefy), Color.White);
                        }
                        else if (caisseList2[x, y] == "<")
                        {
                            spriteBatch.Draw(platg.Texture, new Vector2(y * cote_caisse - coefx, x * cote_caisse - coefy), Color.White);
                        }
                        else if (caisseList2[x, y] == ">")
                        {
                            spriteBatch.Draw(platd.Texture, new Vector2(y * cote_caisse - coefx, x * cote_caisse - coefy), Color.White);
                        }
                        else if (caisseList2[x, y] == "s")
                        {
                            spriteBatch.Draw(sentinelle.Texture, new Vector2(y * cote_caisse - coefx, x * cote_caisse - coefy), Color.White);
                        }
                        else if (caisseList2[x, y] == "h")
                        {
                            spriteBatch.Draw(helico.Texture, new Vector2(y * cote_caisse - coefx, x * cote_caisse - coefy), Color.White);
                        }
                        else if (caisseList2[x, y] == "e")
                        {
                            spriteBatch.Draw(soldat.Texture, new Vector2(y * cote_caisse - coefx, x * cote_caisse - coefy), Color.White);
                        }
                    }
                }
            }

            if (typeObj == "C")
            {
                caisse.Draw(spriteBatch);
            }
            else if (typeObj == "o")
            {
                plateforme.Draw(spriteBatch);
            }
            else if (typeObj == "<")
            {
                platg.Draw(spriteBatch);
            }
            else if (typeObj == ">")
            {
                platd.Draw(spriteBatch);
            }
            else if (typeObj == "s")
            {
                sentinelle.Draw(spriteBatch);
            }
            else if (typeObj == "h")
            {
                helico.Draw(spriteBatch);
            }
            else if (typeObj == "e")
            {
                soldat.Draw(spriteBatch);
            }

            Menu.Draw(spriteBatch, graphics);
            spriteBatch.DrawString(texte, "x: " + Convert.ToString(coefx) + " y: " + Convert.ToString(coefy), new Vector2(20, 20), Color.White);
            spriteBatch.End();

            base.Draw(gameTime);
        }
    }
}
